package com.netty.proxy;

import com.netty.handler.ClientHandler;
import com.netty.pojo.RpcRequest;
import com.netty.pojo.RpcResponse;
import com.netty.serializer.JSONSerializer;
import com.netty.serializer.RpcDecoder;
import com.netty.serializer.RpcEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : zhengyao3@郑瑶
 * @date : 2020/7/3 13:02
 * @Description: RPC动态代理实现类
 */

public class RpcProxy{
    private static ExecutorService executor = new ThreadPoolExecutor(10, 50, 1, TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(100));
    private static ClientHandler clientHandler;
    
    private static void initClientHandler(){
        //1) 初始化UserClientHandler
        clientHandler  = new ClientHandler();
        //2)创建连接池对象
        EventLoopGroup group = new NioEventLoopGroup();
        //3)创建客户端的引导对象
        Bootstrap bootstrap =  new Bootstrap();
        //4)配置启动引导对象
        bootstrap.group(group)
                //设置通道为NIO
                .channel(NioSocketChannel.class)
                //设置请求协议为TCP
                .option(ChannelOption.TCP_NODELAY,true)
                //监听channel 并初始化
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //获取ChannelPipeline
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        //设置编码
                        JSONSerializer serializer = new JSONSerializer();
                        //传输的时候使用RpcReuquest
                        pipeline.addLast(new RpcEncoder(RpcRequest.class, serializer));
                        //返回的时候使用RpcResponse
                        pipeline.addLast(new RpcDecoder(RpcResponse.class, serializer));

                        //添加自定义事件处理器
                        pipeline.addLast(clientHandler);
                    }
                });

        //5)连接服务端
        try {
            bootstrap.connect("127.0.0.1",8899).sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
    
    public static Object getProxy(Class clazz){
        return Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},(proxy,method,args)->{
            RpcRequest rpcRequest = new RpcRequest();
            rpcRequest.setRequestId(UUID.randomUUID().toString());
            rpcRequest.setClassName(clazz.getName());
            rpcRequest.setMethodName(method.getName());
            rpcRequest.setParameters(args);
            rpcRequest.setParameterTypes(method.getParameterTypes());
            if (clientHandler == null) {
                initClientHandler();
            }
            clientHandler.setParam(rpcRequest);
            return executor.submit(clientHandler).get();
        });
    }
    
}
